package nacos

import (
	"errors"
	"fmt"
	"strconv"
	"strings"

	"test/lib/tools/ip"

	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/config_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"
)

//本地调试地址:acm.aliyun.com
type Nacos struct {
	ClientConf constant.ClientConfig
	Client     config_client.IConfigClient
	ServerConf []constant.ServerConfig
}

func New(conf constant.ClientConfig) error {

	if len(conf.Endpoint) == 0 {
		if ip.IsLocal {
			conf.Endpoint = "acm.aliyun.com"
		} else {
			conf.Endpoint = "acm.aliyun.com" // "addr-hz-internal.edas.aliyun.com"
		}
	}

	if len(conf.NamespaceId) == 0 && len(conf.AccessKey) == 0 && len(conf.SecretKey) == 0 {
		if ip.IsLocal {
			conf.NamespaceId = "4bf2ebab-1736-42bb-8e47-0eec2bad64c2"
			conf.AccessKey = "7d56dcd43f5c4ecba1b9c446aed4c87d"
			conf.SecretKey = "u1NswKvEANMUGzBWSpoEVmveg4s="
		} else {
			conf.NamespaceId = "37557c71-6cfa-4aa2-bcc2-840d8627de70"
			conf.AccessKey = "0d33d0cce65b4ea092a9d6f82ba7e2c2"
			conf.SecretKey = "iMEhvI1pLXvN3Cp4fbWnPFKYCL0="
		}
	}

	port := 8848
	if conf.Endpoint == "acm.aliyun.com" {
		port = 8080
	}

	clientConfig := constant.ClientConfig{
		Endpoint:       conf.Endpoint + fmt.Sprintf(":%d", port), //":%d/nacos"
		NamespaceId:    conf.NamespaceId,
		AccessKey:      conf.AccessKey,
		SecretKey:      conf.SecretKey,
		TimeoutMs:      5 * 1000,
		ListenInterval: 30 * 1000,
	}

	serverConfigs := []constant.ServerConfig{{
		IpAddr:      conf.Endpoint,
		ContextPath: "/nacos",
		Port:        uint64(port),
	}}

	configClient, err := clients.CreateConfigClient(map[string]interface{}{
		"serverConfigs": serverConfigs,
		"clientConfig":  clientConfig,
	})
	if err != nil {
		return err
	}
	DefNacos = &Nacos{
		ClientConf: conf,
		Client:     configClient,
		ServerConf: serverConfigs,
	}
	return nil
}

func (n *Nacos) GetInt(key string, def ...int) int {
	s, err := n.Get(key)
	if err != nil {
		if len(def) > 0 {
			return def[0]
		}
	}
	num, err := strconv.Atoi(s)
	if err != nil {
		if len(def) > 0 {
			return def[0]
		}
	}
	return num
}

func (n *Nacos) GetString(key string, def ...string) string {
	s, err := n.Get(key)
	if err != nil {
		if len(def) > 0 {
			return def[0]
		}
	}
	return s
}

func (n *Nacos) GetBool(key string, def ...bool) bool {
	s, err := n.Get(key)
	if err != nil {
		if len(def) > 0 {
			return def[0]
		}
	}
	if s == "true" || s == "True" || s == "TRUE" {
		return true
	} else if s == "false" || s == "False" || s == "FALSE" {
		return false
	} else if len(def) > 0 {
		return def[0]
	}
	return false
}

func (n *Nacos) Get(key string) (string, error) {
	if n == nil {
		return "", errors.New("uninitialized")
	}
	list := strings.Split(key, ".")
	if len(list) < 2 {
		return "", errors.New("invalid config")
	}
	return n.Client.GetConfig(vo.ConfigParam{
		DataId: list[1],
		Group:  list[0]})
}

func (n *Nacos) Set(key string, val string) error {
	if n == nil {
		return errors.New("uninitialized")
	}
	list := strings.Split(key, ".")
	if len(list) < 2 {
		return errors.New("Invalid Config")
	}
	succ, err := n.Client.PublishConfig(vo.ConfigParam{
		DataId:  list[1],
		Group:   list[0],
		Content: val})
	if err != nil {
		return err
	}
	if !succ {
		return errors.New("set config fail.")
	}
	return nil
}

func (n *Nacos) Del(key string) error {
	if n == nil {
		return errors.New("uninitialized")
	}
	list := strings.Split(key, ".")
	if len(list) < 2 {
		return errors.New("invalid config")
	}
	succ, err := n.Client.DeleteConfig(vo.ConfigParam{
		DataId: list[1],
		Group:  list[0],
	})
	if err != nil {
		return err
	}
	if !succ {
		return errors.New("delete config fail.")
	}
	return nil
}
